package com.gtmc.gclub.error;

import java.util.Collections;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.web.AbstractErrorController;
import org.springframework.boot.autoconfigure.web.BasicErrorController;
import org.springframework.boot.autoconfigure.web.ErrorAttributes;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.ErrorProperties.IncludeStacktrace;
import org.springframework.boot.autoconfigure.web.ErrorViewResolver;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.gtmc.gclub.chat.bean.Result;

@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
public class GateWayErrorController extends AbstractErrorController {
	private Logger logger = LoggerFactory.getLogger(this.getClass());

	private final ErrorProperties errorProperties;

	public GateWayErrorController(ErrorAttributes errorAttributes) {
		this(errorAttributes, new ErrorProperties());
	}

	/**
	 * Create a new {@link BasicErrorController} instance.
	 * 
	 * @param errorAttributes
	 *            the error attributes
	 * @param errorProperties
	 *            configuration properties
	 */
	public GateWayErrorController(ErrorAttributes errorAttributes, ErrorProperties errorProperties) {
		this(errorAttributes, errorProperties, Collections.<ErrorViewResolver>emptyList());
	}

	/**
	 * Create a new {@link BasicErrorController} instance.
	 * 
	 * @param errorAttributes
	 *            the error attributes
	 * @param errorProperties
	 *            configuration properties
	 * @param errorViewResolvers
	 *            error view resolvers
	 */
	public GateWayErrorController(ErrorAttributes errorAttributes, ErrorProperties errorProperties,
			List<ErrorViewResolver> errorViewResolvers) {
		super(errorAttributes, errorViewResolvers);
		Assert.notNull(errorProperties, "ErrorProperties must not be null");
		this.errorProperties = errorProperties;
	}

	public String getErrorPath() {
		return this.errorProperties.getPath();
	}

	@RequestMapping(produces = "text/html")
	public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
		HttpStatus status = getStatus(request);
		Map<String, Object> model = Collections
				.unmodifiableMap(getErrorAttributes(request, isIncludeStackTrace(request, MediaType.TEXT_HTML)));
		try {
			String[] ebody = ((String) model.get("exception")).split("\\.");
			String e = ebody[ebody.length - 1];
			String message = (String) model.get("message");
			logger.error("异常，ERROR:" + (String) model.get("exception") + "\r\n" + "message:" + message);
			if ("MyException".equals(e)) {
				// 自定义异常
				if ("permission".equals(message)) {
					return new ModelAndView("error/permiss");
				} else if ("back".equals(message)) {
					return new ModelAndView("error/back");
				}
			}
			response.setStatus(status.value());
			ModelAndView modelAndView = resolveErrorView(request, response, status, model);
			return (modelAndView == null ? new ModelAndView("error", model) : modelAndView);
		} catch (Exception e) {
			logger.error(e.getMessage());
			if (model != null) {
				model.put("message", "系统异常");
			}
			response.setStatus(status.value());
			ModelAndView modelAndView = resolveErrorView(request, response, status, model);
			return (modelAndView == null ? new ModelAndView("error", model) : modelAndView);
		}

	}

	@RequestMapping
	@ResponseBody
	public Result<String> error(HttpServletRequest request) {
		try {
			Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL));
			String[] ebody = ((String) body.get("exception")).split("\\.");
			String e = ebody[ebody.length - 1];
			String message = (String) body.get("message");
			logger.error("异常，ERROR:" + (String) body.get("exception") + "\r\n" + "message:" + message);
			if ("MissingServletRequestParameterException".equals(e)) {
				// 参数校验失败
				return new Result<String>(0, null, "请求参数异常");
			} else if ("MyException".equals(e)) {
				// 自定义异常
				return new Result<String>(0, null, message);
			} else if ("BizException".equals(e)) {
				// 业务异常
				return new Result<String>(200, null, message);
			} else {
				return new Result<String>(0, null, "系统异常");
			}
		} catch (Exception e) {
			logger.error("异常，ERROR:" + e.getClass() + "\r\n" + "message:" + e.getMessage());
			return new Result<String>(0, null, "系统异常");
		}

	}

	/**
	 * Determine if the stacktrace attribute should be included.
	 * 
	 * @param request
	 *            the source request
	 * @param produces
	 *            the media type produced (or {@code MediaType.ALL})
	 * @return if the stacktrace attribute should be included
	 */
	protected boolean isIncludeStackTrace(HttpServletRequest request, MediaType produces) {
		IncludeStacktrace include = getErrorProperties().getIncludeStacktrace();
		if (include == IncludeStacktrace.ALWAYS) {
			return true;
		}
		if (include == IncludeStacktrace.ON_TRACE_PARAM) {
			return getTraceParameter(request);
		}
		return false;
	}

	/**
	 * Provide access to the error properties.
	 * 
	 * @return the error properties
	 */
	protected ErrorProperties getErrorProperties() {
		return this.errorProperties;
	}

}
